﻿using System;
using System.Collections.Generic;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows;

namespace WeatherReaderMVC
{
    public class WeatherReport
    {

        #region WeatherProperties

        public WeatherReport()
        {
            forecast = new List<WeatherRange>();
        }

        private WeatherPoint latestWeather;
        public WeatherPoint LatestWeather
        {
            get { return latestWeather; }
            set { latestWeather = value; }
        }

        private List<WeatherRange> forecast;
        public List<WeatherRange> Forecast
        {
            get { return forecast; }
            set { forecast = value; }
        }

        private Location location;
        public Location Location
        {
            get { return location; }
            set { location = value; }
        }

        private UnitsSystems unitsSystem;
        public UnitsSystems UnitsSystem
        {
            get { return unitsSystem; }
            set { unitsSystem = value; }
        }

        #endregion

        #region UIProperties
        // Following functions are for background images and color
        //  Consider moving them to the UI class??

        private int skyCode;
        public int SkyCode
        {
            get { return skyCode; }
            set { skyCode = value; }
        }

        #region UndockedBackgroundProperties
        public Image BackgroundImage
        {
            get
            {
                Image bgi = new Image();
                if (!isNight())
                {
                    if (44 == skyCode || 36 == skyCode || 34 == skyCode || 32 == skyCode || 31 == skyCode)
                    {
                        bgi.Source = new BitmapImage(new Uri("Images/undocked_sun.png", UriKind.Relative));
                    }
                }
                else
                {
                    string moonShape = computeMoonShape();
                    if (44 == skyCode || 36 == skyCode || 34 == skyCode || 32 == skyCode || 31 == skyCode)
                    {
                        bgi.Source = new BitmapImage(new Uri("Images/undocked_moon-" + moonShape + ".png", UriKind.Relative));
                    }
                }
                return bgi;
            }
        }
        public Image BackgroundImage2
        {
            get
            {
                Image bgi2 = new Image();
                string theWeatherState = weatherState(skyCode);
                bgi2.Source = new BitmapImage(new Uri("Images/undocked_" + theWeatherState + ".png", UriKind.Relative));
                return bgi2;
            }
        }
        public Image BackgroundImage3
        {
            get
            {
                Image bgi3 = new Image();
                if (isNight())
                {
                    bgi3.Source = new BitmapImage(new Uri("Images/BLACK-base.png", UriKind.Relative));
                }
                else
                {
                    if (44 == skyCode || 36 == skyCode || 34 == skyCode || 32 == skyCode || 31 == skyCode)
                    {
                        bgi3.Source = new BitmapImage(new Uri("Images/BLUE-base.png", UriKind.Relative));
                    }
                    else
                    {
                        bgi3.Source = new BitmapImage(new Uri("Images/GRAY-base.png", UriKind.Relative));
                    }
                }
                return bgi3;
            }
        }
        #endregion

        #region DockedBackgroundProperties
        public Image DockedBackgroundImage
        {
            get
            {
                Image dbgi = new Image();
                if (!isNight())
                {
                    if (44 == skyCode || 36 == skyCode || 34 == skyCode || 32 == skyCode || 31 == skyCode)
                    {
                        dbgi.Source = new BitmapImage(new Uri("Images/docked_sun.png", UriKind.Relative));
                    }
                }
                else
                {
                    string moonShape = computeMoonShape();
                    if (44 == skyCode || 36 == skyCode || 34 == skyCode || 32 == skyCode || 31 == skyCode)
                    {
                        dbgi.Source = new BitmapImage(new Uri("Images/docked_moon-" + moonShape + ".png", UriKind.Relative));
                    }
                }
                return dbgi;
            }
        }
        public Image DockedBackgroundImage2
        {
            get
            {
                Image dbgi2 = new Image();
                string theWeatherState = weatherState(skyCode);
                dbgi2.Source = new BitmapImage(new Uri("Images/docked_" + theWeatherState + ".png", UriKind.Relative));
                return dbgi2;
            }
        }
        public Image DockedBackgroundImage3
        {
            get
            {
                Image dbgi3 = new Image();
                if (isNight())
                {
                    dbgi3.Source = new BitmapImage(new Uri("Images/BLACKDOCKED-base.png", UriKind.Relative));
                }
                else
                {
                    if (44 == skyCode || 36 == skyCode || 34 == skyCode || 32 == skyCode || 31 == skyCode)
                    {
                        dbgi3.Source = new BitmapImage(new Uri("Images/BLUEDOCKED-base.png", UriKind.Relative));
                    }
                    else
                    {
                        dbgi3.Source = new BitmapImage(new Uri("Images/GRAYDOCKED-base.png", UriKind.Relative));
                    }
                }
                return dbgi3;
            }
        }
        #endregion

        public Brush TextColor
        {
            get
            {
                return (isNight()) ?
                    Brushes.White:
                    Brushes.Black;
                    //new SolidColorBrush(Color.FromArgb(0x3f, 0xff, 0xff, 0xff)) :
                    //new SolidColorBrush(Color.FromArgb(0xbf, 0x00, 0x00, 0x00));
            }
        }
        public Uri WeatherUri
        {
            get
            {
                return new Uri("http://weather.msn.com/local.aspx?wealocations=" + ((MsnLocation)location).LocationCode);
            }
        }

        #endregion

        #region PrivateMethods

        private string weatherState(int code)
        {
            string theWeatherState = "";
            switch (code)
            {
                case (26):
                case (27):
                case (28):
                    theWeatherState = "cloudy";
                    break;
                case (35):
                case (39):
                case (45):
                case (46):
                    theWeatherState = "few-showers";
                    break;
                case (19):
                case (20):
                case (21):
                case (22):
                    theWeatherState = "foggy";
                    break;
                case (29):
                case (30):
                case (33):
                    theWeatherState = "partly-cloudy";
                    break;
                case (5):
                case (13):
                case (14):
                case (15):
                case (16):
                case (18):
                case (25):
                case (41):
                case (42):
                case (43):
                    theWeatherState = "snow";
                    break;
                case (1):
                case (2):
                case (3):
                case (4):
                case (37):
                case (38):
                case (47):
                    theWeatherState = "thunderstorm";
                    break;
                case (31):
                case (32):
                case (34):
                case (36):
                case (44):        // Note 44- "Data Not Available"
                    theWeatherState = "";
                    break;
                case (23):
                case (24):
                    theWeatherState = "windy";
                    break;
                case (9):
                case (10):
                case (11):
                case (12):
                case (40):
                    theWeatherState = "rainy";
                    break;
                case (6):
                case (7):
                case (8):
                case (17):
                    theWeatherState = "hail";
                    break;
                default:
                    theWeatherState = "";
                    break;
            }
            return theWeatherState;
        }

        private bool isNight()
        {

            // TODO: Make the isNight algorithm more sophisticated
            if ((latestWeather.SkyCondition.SkyCondition.Contains("Cloudy")) ||
                           (latestWeather.SkyCondition.SkyCondition.Contains("Fair")) ||
                           (latestWeather.SkyCondition.SkyCondition.Contains("Sprinkles")))
            {
                return true;
            }
            return (LatestWeather.Time.Hour >= 6 && LatestWeather.Time.Hour <= 18) ? false : true;
             
        }

        private string computeMoonShape()
        {
            int Year = LatestWeather.Time.Year;
            int Month = LatestWeather.Time.Month;
            int Day = LatestWeather.Time.Day;
            // Variable names used: J, K1, K2, K3, MM, P2, V, YY
            //double P2 = 3.14159 * 2;    
            int YY = Year - (int)((12 - Month) / 10);
            int MM = Month + 9;
            if (MM >= 12) { MM = MM - 12; }
            int K1 = (int)(365.25 * (YY + 4712));
            int K2 = (int)(30.6 * MM + .5);
            int K3 = (int)((int)((YY / 100) + 49) * .75) - 38;
            // J is the Julian date at 12h UT on day in question
            int J = K1 + K2 + Day + 59;
            // Adjust for Gregorian calendar, if applicable   
            if (J > 2299160) { J = J - K3; }
            // Calculate illumination (synodic) phase
            double V = (J - 2451550.1) / 29.530588853;
            V = V - (int)(V);
            // Normalize values to range from 0 to 1
            if (V < 0) { V = V + 1; }
            // Moon's age in days from New Moon
            double AG = V * 29.53;
            string retVal;
            if ((AG > 27.6849270496875) || (AG <= 1.8456618033125))
            {
                retVal = "New";
            }
            else if ((AG > 1.8456618033125) && (AG <= 5.5369854099375))
            {
                retVal = "Waxing-Crescent";
            }
            else if ((AG > 5.5369854099375) && (AG <= 9.2283090165625))
            {
                retVal = "First-Quarter";
            }
            else if ((AG > 9.2283090165625) && (AG <= 12.9196326231875))
            {
                retVal = "Waxing-Gibbous";
            }
            else if ((AG > 12.9196326231875) && (AG <= 16.6109562298125))
            {
                retVal = "Full";
            }
            else if ((AG > 16.6109562298125) && (AG <= 20.3022798364375))
            {
                retVal = "Waning-Gibbous";
            }
            else if ((AG > 20.3022798364375) && (AG <= 23.9936034430625))
            {
                retVal = "Last-Quarter";
            }
            else if ((AG > 23.9936034430625) && (AG <= 27.6849270496875))
            {
                retVal = "Waning-Crescent";
            }
            else
            {
                retVal = "Full";
            }

            return retVal;
        }

        #endregion

    }
}
